//package me.zhengjie.utils;
//
//import com.sun.jna.Native;
//import com.sun.jna.Pointer;
//import me.zhengjie.rest.HK.VideoPreview;
//import me.zhengjie.service.HCNetSDK;
//import me.zhengjie.service.PlayCtrl;
//import me.zhengjie.service.vo.LoginVo;
//import me.zhengjie.service.vo.MyBlockingQueue;
//import org.springframework.stereotype.Component;
//
//import javax.annotation.PostConstruct;
//import javax.annotation.PreDestroy;
//import java.util.ArrayList;
//import java.util.List;
//import java.util.concurrent.ArrayBlockingQueue;
//import java.util.concurrent.BlockingQueue;
//
//@Component
//public class PreverViewUntil {
//    static boolean isInit = false;//是否初始化
//    public static HCNetSDK hCNetSDK = null;
//    public static PlayCtrl playControl = null;
//    static PreverViewUntil.FExceptionCallBack_Imp fExceptionCallBack;//异常捕获回调
//
//    /**
//     * 异常信息捕获接受类
//     */
//    static class FExceptionCallBack_Imp implements HCNetSDK.FExceptionCallBack {
//        public void invoke(int dwType, int lUserID, int lHandle, Pointer pUser) {
//            switch(dwType)
//            {
//                case HCNetSDK.EXCEPTION_AUDIOEXCHANGE:		//语音对讲时网络异常
//                    System.out.println("登录句柄:"+lUserID+"语音对讲异常");
//                    break;
//                case HCNetSDK.EXCEPTION_ALARM:			//报警上传时网络异常
//                    System.out.println("登录句柄:"+lUserID+"报警上传时网络异常");
//                    break;
//                case HCNetSDK.EXCEPTION_PREVIEW:			//网络预览时异常
//                    System.out.println("登录句柄:"+lUserID+"网络预览时异常");
//                    //TODO: 关闭网络预览
//                    break;
//                case HCNetSDK.EXCEPTION_SERIAL:			//透明通道传输时异常
//                    System.out.println("登录句柄:"+lUserID+"透明通道传输时异常");
//                    //TODO: 关闭透明通道
//                    break;
//                case HCNetSDK.EXCEPTION_RECONNECT:		//预览时重连
//                    System.out.println("登录句柄:"+lUserID+"预览时重连");
//                    break;
//                default:
//                    System.out.println("登录句柄:"+lUserID+",异常事件类型:"+Integer.toHexString(dwType));
//                    System.out.println("具体错误参照 SDK网络使用手册中：NET_DVR_SetExceptionCallBack_V30 方法中的异常定义！");
//                    break;
//            }
//            return;
//        }
//    }
//
//
//    /**
//     * 动态库加载
//     * @return
//     */
//    private static boolean CreateSDKInstance() {
//        if (hCNetSDK == null) {
//            synchronized (HCNetSDK.class) {
//                String strDllPath = "";
//                try {
//                    //win系统加载库路径
//                    //strDllPath = System.getProperty("user.dir") + "\\eladmin-tools\\src\\main\\java\\me\\zhengjie\\config\\HK\\HCNetSDK.dll";
//                    //hCNetSDK = (HCNetSDK) Native.loadLibrary(strDllPath, HCNetSDK.class);
//                    hCNetSDK = (HCNetSDK) Native.loadLibrary("D:\\hjProject\\hanjiang-admin-api\\eladmin-tools\\src\\main\\java\\me\\zhengjie\\config\\HK\\HCNetSDK.dll", HCNetSDK.class);
//                    //Linux系统加载库路径
////                    strDllPath = System.getProperty("user.dir") + "/eladmin-tools/src/main/java/me/zhengjie/config/HKLinux/libhcnetsdk.so";
////                    hCNetSDK = (HCNetSDK) Native.loadLibrary(strDllPath, HCNetSDK.class);
//                } catch (Exception ex) {
//                    System.out.println("loadLibrary: " + strDllPath + " Error: " + ex.getMessage());
//                    return false;
//                }
//            }
//        }
//        return true;
//    }
//    /**
//     * 播放库加载
//     * @return
//     */
//    private static boolean CreatePlayInstance() {
//        if (playControl == null) {
//            synchronized (PlayCtrl.class) {
//                String strPlayPath = "";
//                try {
//                    //win系统加载库路径
//                    //strPlayPath = System.getProperty("user.dir") + "\\eladmin-tools\\src\\main\\java\\me\\zhengjie\\config\\HK\\PlayCtrl.dll";
//                    //playControl = (PlayCtrl) Native.loadLibrary(strPlayPath, PlayCtrl.class);
//                    playControl = (PlayCtrl) Native.loadLibrary("D:\\hjProject\\hanjiang-admin-api\\eladmin-tools\\src\\main\\java\\me\\zhengjie\\config\\HK\\PlayCtrl.dll", PlayCtrl.class);
//                    //Linux系统加载库路径
//                    //playControl = (PlayCtrl) Native.loadLibrary("D:\\hjProject\\hanjiang-admin-api\\eladmin-tools\\src\\main\\java\\me\\zhengjie\\config\\HK\\PlayCtrl.dll", PlayCtrl.class);
//                    //strPlayPath = System.getProperty("user.dir") + "/eladmin-tools/src/main/java/me/zhengjie/config/HKLinux/libPlayCtrl.so";
//                    //playControl = (PlayCtrl) Native.loadLibrary(strPlayPath, PlayCtrl.class);
//                } catch (Exception ex) {
//                    System.out.println("loadLibrary: " + strPlayPath + " Error: " + ex.getMessage());
//                    return false;
//                }
//            }
//        }
//        return true;
//    }
//
//    /**
//     * 类初始化时加载SDK
//     * @PostConstruct 便于直接加载注入类
//     */
//    @PostConstruct
//    public static void init() {
//        System.out.println("加载海康威视SDK dll");
//        if (hCNetSDK == null&&playControl==null) {
//            if (!CreateSDKInstance()) {
//                System.out.println("Load SDK fail");
//                return;
//            }
//            if (!CreatePlayInstance()) {
//                System.out.println("Load PlayCtrl fail");
//                return;
//            }
//        }
//        System.out.println("海康威视SDK dll加载成功");
//
//        //linux系统建议调用以下接口加载组件库
////        HCNetSDK.BYTE_ARRAY ptrByteArray1 = new HCNetSDK.BYTE_ARRAY(256);
////        HCNetSDK.BYTE_ARRAY ptrByteArray2 = new HCNetSDK.BYTE_ARRAY(256);
////        //这里是库的绝对路径，请根据实际情况修改，注意改路径必须有访问权限
////        String strPath1 = System.getProperty("user.dir") + "/eladmin-tools/src/main/java/me/zhengjie/config/HKLinux/libcrypto.so.1.1";
////        String strPath2 = System.getProperty("user.dir") + "/eladmin-tools/src/main/java/me/zhengjie/config/HKLinux/libssl.so.1.1";
////        System.arraycopy(strPath1.getBytes(), 0, ptrByteArray1.byValue, 0, strPath1.length());
////        ptrByteArray1.write();
////        hCNetSDK.NET_DVR_SetSDKInitCfg(3, ptrByteArray1.getPointer());
////        System.arraycopy(strPath2.getBytes(), 0, ptrByteArray2.byValue, 0, strPath2.length());
////        ptrByteArray2.write();
////        hCNetSDK.NET_DVR_SetSDKInitCfg(4, ptrByteArray2.getPointer());
////        String strPathCom = System.getProperty("user.dir") + "/eladmin-tools/src/main/java/me/zhengjie/config/HKLinux";
////        HCNetSDK.NET_DVR_LOCAL_SDK_PATH struComPath = new HCNetSDK.NET_DVR_LOCAL_SDK_PATH();
////        System.arraycopy(strPathCom.getBytes(), 0, struComPath.sPath, 0, strPathCom.length());
////        struComPath.write();
////        hCNetSDK.NET_DVR_SetSDKInitCfg(2, struComPath.getPointer());
//
//
//
//        System.out.println("开始初始化海康威视Sdk");
//        //SDK初始化，一个程序只需要调用一次
//        boolean initSuc = hCNetSDK.NET_DVR_Init();
//        if (initSuc != true) {
//            System.out.println("初始化海康威视Sdk失败");
//        }
//        System.out.println("海康威视Sdk初始化成功！");
//        System.out.println("开始设置异常消息回调");
//        //异常消息回调
//        if(fExceptionCallBack == null)
//        {
//            fExceptionCallBack = new PreverViewUntil.FExceptionCallBack_Imp();
//        }
//        Pointer pUser = null;
//        if (!hCNetSDK.NET_DVR_SetExceptionCallBack_V30(0, 0, fExceptionCallBack, pUser)) {
//            return ;
//        }
//        System.out.println("设置异常消息回调成功");
//        System.out.println("开始设置启动SDK写日志");
//        //启动SDK写日志
//        hCNetSDK.NET_DVR_SetLogToFile(3, "..\\sdkLog\\", false);
//        isInit = true;
//    }
//
//    //类销毁时清理sdk
//    @PreDestroy
//    public void clearSdk() {
//        if (null!=hCNetSDK)
//        {
//            //SDK反初始化，释放资源，只需要退出时调用一次
//            hCNetSDK.NET_DVR_Cleanup();
//        }
//    }
//
//
//
//
//    /**
//     * 摄像头登录（支持批量操作）
//     * @param loginVos
//     * @return
//     */
//    public static List<LoginVo> login(List<LoginVo> loginVos) {
//        if(loginVos.size()<1) return loginVos;
//        for (int i = 0; i < loginVos.size(); i++) {
//            LoginVo loginVo = loginVos.get(i);
//            if(!isInit)
//            {
//                init();
//            }
//            //如果已经登录，就先退出登陆
//            String userIdByIp = MyBlockingQueue.findUserIdByIp(loginVo.getIp());
//            if(null!=userIdByIp)
//            {
//                //自动判断是否在预览并退出
//                PreverViewUntil.logoutPlayView(userIdByIp);
//            }
//            //登录设备，每一台设备分别登录; 登录句柄是唯一的，可以区分设备
//            HCNetSDK.NET_DVR_USER_LOGIN_INFO m_strLoginInfo = new HCNetSDK.NET_DVR_USER_LOGIN_INFO();//设备登录信息
//            HCNetSDK.NET_DVR_DEVICEINFO_V40 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40();//设备信息
//            String m_sDeviceIP = loginVo.getIp();//设备ip地址
//            m_strLoginInfo.sDeviceAddress = new byte[HCNetSDK.NET_DVR_DEV_ADDRESS_MAX_LEN];
//            System.arraycopy(m_sDeviceIP.getBytes(), 0, m_strLoginInfo.sDeviceAddress, 0, m_sDeviceIP.length());
//            String m_sUsername = loginVo.getUserName();//设备用户名
//            m_strLoginInfo.sUserName = new byte[HCNetSDK.NET_DVR_LOGIN_USERNAME_MAX_LEN];
//            System.arraycopy(m_sUsername.getBytes(), 0, m_strLoginInfo.sUserName, 0, m_sUsername.length());
//            String m_sPassword = loginVo.getPassword();//设备密码
//            m_strLoginInfo.sPassword = new byte[HCNetSDK.NET_DVR_LOGIN_PASSWD_MAX_LEN];
//            System.arraycopy(m_sPassword.getBytes(), 0, m_strLoginInfo.sPassword, 0, m_sPassword.length());
//            m_strLoginInfo.wPort = loginVo.getPort(); //SDK端口
//            m_strLoginInfo.bUseAsynLogin = false; //是否异步登录：0- 否，1- 是
//            m_strLoginInfo.write();
//
//            String ipPortStr=loginVo.getIp()+":"+loginVo.getPort();
//            System.out.println("开始登录:"+ipPortStr);
//            int lUserID = hCNetSDK.NET_DVR_Login_V40(m_strLoginInfo, m_strDeviceInfo);
//            if (lUserID == -1) {
//                System.out.println(ipPortStr+"登录失败，错误码为" + hCNetSDK.NET_DVR_GetLastError());
//                loginVo.setLoginStatus("0");
//                loginVo.setLoginMessage("登录失败，错误码为" + hCNetSDK.NET_DVR_GetLastError());
//                loginVo.setLUserID(null);
//            } else {
//                //判断DVR工作状态
////                HCNetSDK.NET_DVR_WORKSTATE_V30 devwork = new HCNetSDK.NET_DVR_WORKSTATE_V30();
////                boolean net_DVR_GetDVRWorkState_V30 = hCNetSDK.NET_DVR_GetDVRWorkState_V30(lUserID, devwork);
////                if (net_DVR_GetDVRWorkState_V30) {
////                    //设备的状态,0-正常,1-CPU占用率太高,超过85%,2-硬件错误,例如串口死掉
////                    if(devwork.dwDeviceStatic!=0)
////                    {
////
////                    }
////                }
////                else
////                {
////                    //未知错误：获取DVR工作状态失败
////                }
//                //这里直接认为登陆成功就能预览吧。。
//                String successStr=m_sDeviceIP + ":设备登录成功! " + "设备序列号:" +
//                        new String(m_strDeviceInfo.struDeviceV30.sSerialNumber).trim();
//                System.out.println(successStr);
//                loginVo.setLoginMessage(successStr);
//                loginVo.setLoginStatus("1");
//                loginVo.setLUserID(lUserID);
//                m_strDeviceInfo.read();
//                //记录ip已经登录
//                MyBlockingQueue.IPToUserIdMap.put(loginVo.getIp(),loginVo.getLUserID().toString());
//            }
//        }
//        return loginVos;
//    }
//
//    /***
//     * 实时预览某个摄像机
//     * @param vo
//     * @return
//     */
//    public static LoginVo playView(LoginVo vo)
//    {
//        //注释掉的代码也可以参考，去掉注释可以运行
//        //VideoDemo.getIPChannelInfo(lUserID); //获取IP通道
//        //int lDChannel = (int)m_strDeviceInfo.struDeviceV30.byStartDChan + lChannel -1;
//        String ipPortStr=vo.getIp()+":"+vo.getPort();
//        System.out.println("预览通道号: " + vo.getLDChannel());
//        System.out.println("尝试预览连接:"+ipPortStr);
//        VideoPreview.realPlay(vo.getLUserID(), vo.getLDChannel());//预览
//        if(VideoPreview.lPlayStatus)
//        {
//            vo.setPlayStatus("1");
//            vo.setPlayMessage("预览请求成功！");
//            vo.setLPlayID(VideoPreview.lPlay);
//            System.out.println("预览请求成功："+vo);
//            //创建数据体，等待视频流实时回调
//            BlockingQueue bq = new ArrayBlockingQueue<>(10);
//            MyBlockingQueue.bpMap.put(vo.getLUserID().toString(),bq);
//            MyBlockingQueue.PlayToUserIdMap.put(vo.getLPlayID().toString(),vo.getLUserID().toString());
//        }else
//        {
//            vo.setPlayStatus("0");
//            vo.setPlayMessage("预览失败："+VideoPreview.lPlayErrorMassage);
//            vo.setLPlayID(null);
//        }
//        return vo;
//    }
//
//
//    /**
//     * 登录并播放某个摄像头视频
//     */
//    public static LoginVo loginAndPlayView(LoginVo loginVo) {
//        if(!isInit)
//        {
//            init();
//        }
//        //如果已经登录，就先退出登陆
//        String userIdByIp = MyBlockingQueue.findUserIdByIp(loginVo.getIp());
//        if(null!=userIdByIp)
//        {
//            //自动判断是否在预览并退出
//          PreverViewUntil.logoutPlayView(userIdByIp);
//        }
//        //登录
//        List<LoginVo> loginVos = new ArrayList<>();
//        loginVos.add(loginVo);
//        loginVos = login(loginVos);
//        String ipPortStr=loginVo.getIp()+":"+loginVo.getPort();
//        if("1".equals(loginVo.getLoginStatus()))
//        {
//            //预览
//            if("1".equals(loginVos.get(0).getLoginStatus()))
//            {
//                playView(loginVos.get(0));
//            }
//            else
//            {
//                System.out.println(ipPortStr+"----登陆成功，但是预览失败!");
//                //登录并预览接口中，如果登陆成功但是预览失败,自动退出登录-清理数据体
//                PreverViewUntil.logoutPlayView(loginVo.getLUserID().toString());
//            }
//        }
//        else
//        {
//            System.out.println(ipPortStr+"----登陆失败!");
//        }
//        return loginVos.get(0);
//    }
//
//    /**
//     * 某个摄像头退出登录
//     * @param lUserID  登录句柄
//     * @param lPlayID  预览句柄
//     */
//    public static void logoutPlayView(String lUserID,String lPlayID) {
//        if(null!=hCNetSDK&&MyBlockingQueue.bpMap.containsKey(lUserID))
//        {
//            if (hCNetSDK.NET_DVR_StopRealPlay(Integer.valueOf(lPlayID)))
//            {
//                System.out.println("停止预览成功");
//            }
//            //退出程序时调用，每一台设备分别注销
//            if (hCNetSDK.NET_DVR_Logout(Integer.valueOf(lUserID))) {
//                System.out.println("注销登录成功");
//            }
//            //清理数据体
//            MyBlockingQueue.clearByUserId(lUserID,true);
//        }
//    }
//
//    /**
//     * 某个摄像头退出登录，自动判断是否在预览并停止
//     * @param lUserID  登录句柄
//     */
//    public static void logoutPlayView(String lUserID) {
//        if(null!=hCNetSDK &&MyBlockingQueue.bpMap.containsKey(lUserID))
//        {
//            String playId = MyBlockingQueue.findPlayIdByUserId(lUserID);
//            if(null!=playId)
//            {
//                if (hCNetSDK.NET_DVR_StopRealPlay(Integer.valueOf(playId)))
//                {
//                    System.out.println("停止预览成功");
//                }
//            }
//            //退出程序时调用，注销登录
//            if (hCNetSDK.NET_DVR_Logout(Integer.valueOf(lUserID))) {
//                System.out.println("注销登录成功");
//            }
//            //清理数据体
//            MyBlockingQueue.clearByUserId(lUserID,true);
//        }
//    }
//
//    /**
//     * 只关闭某个摄像头预览，但不退出登录
//     * @param loginVo
//     */
//    public static LoginVo logoutPlayViewOnly(LoginVo loginVo) {
//        if(null!=hCNetSDK)
//        {
//            if(null!=loginVo.getLPlayID())
//            {
//                if (hCNetSDK.NET_DVR_StopRealPlay(loginVo.getLPlayID()))
//                {
//                    System.out.println("停止预览成功");
//                    loginVo.setLPlayID(null);
//                    loginVo.setPlayMessage("停止预览成功");
//                    loginVo.setLoginStatus("0");
//                }
//                else
//                {
//                    //接口返回失败请调用NET_DVR_GetLastError获取错误码，通过错误码判断出错原因。
//                    loginVo.setPlayMessage("停止预览失败：接口返回失败请调用NET_DVR_GetLastError获取错误码，通过错误码判断出错原因。");
//                }
//            }
//            //清理数据体
//            MyBlockingQueue.clearByUserId(loginVo.getLUserID().toString(),false);
//        }
//        return loginVo;
//    }
//}
